import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  AxiosError
} from 'axios'
import FSMessage from '@/utils/message'
import { TokenKey } from '#/constant'
import {
  getCookies,
  getSessionStorage,
  setSessionStorage,
  cleanSessionStorage
} from '@/utils/storage'
import { isObject } from '@/utils/is'
import { number } from 'echarts'

const config = {
  baseURL: process.env.VUE_APP_URL,
  // baseURL: "http://localhost:3000/api",
  timeout: 10000
}

interface Result {
  code: number;
  msg: string;
}

interface ResultWithData<T = any> extends Result {
  data?: T;
}

class RequestHttp {
  private service!: AxiosInstance;

  public constructor(config: AxiosRequestConfig) {
    this.service = axios.create(config)

    // 请求拦截
    this.service.interceptors.request.use(
      (config: AxiosRequestConfig) => {
        const Authorization = getCookies(TokenKey) || ''
        if (Authorization) {
          return {
            ...config,
            headers: {
              Authorization: 'Bearer ' + Authorization
            }
          }
        }
        // 防止重复请求
        if (
          ['get', 'GET', 'post', 'POST', 'delete', 'DELETE'].includes(
            config.method as string
          )
        ) {
          const sessionObj = {
            time: new Date().getTime()
          }
          const preRequestTime = getSessionStorage('preRequestTime')
          if (!preRequestTime) {
            setSessionStorage('preRequestTime', '' + sessionObj.time)
            setTimeout(() => {
              cleanSessionStorage('preRequestTime')
            }, 1000)
          } else {
            FSMessage.error('请勿重复提交')
            return Promise.reject('请勿重复提交')
          }
        }
        return config
      },
      (error: AxiosError) => {
        return Promise.reject(error)
      }
    )

    // 响应拦截
    this.service.interceptors.response.use(
      (response: any) => {
        const { data, status, config, statusText } = response
        const innerData = data.data
        const innerStatus = data.status;
        // console.log(data, 'data');
        // console.log(status, 'status');

        if (status === 500) { // out status
          FSMessage.error("系统异常")
          return data
        } else {
          if (innerStatus === 500) {
            FSMessage.error(innerData.message)
          } else {
            if (innerData && innerData.hasOwnProperty("status") && (typeof innerData.status === 'number') && ![200, 201, 0, 1, 2, '0', '1', '2'].includes(innerData.status)) {
              console.log("触发了");
              FSMessage.error(innerData.message)
            }
          }
          return data;
        }
      },
      (error: AxiosError<any, any>) => {
        if (error.response.status === 401) {
          // token 过期或不存在
          FSMessage.confirm('登录状态已过期，请重新登录', '提示')
            .then((res) => { })
            .catch((e) => { })
        }
        // @ts-ignore
        const data = error.response.data ?? {}
        FSMessage.error(data.data)
        return Promise.reject(data.data)
      }
    )
  }

  // 网络请求常用方法封装, 返回的数据格式需要传递，例如 .get<User>("",{})
  public get<T>(
    url: string,
    config?: AxiosRequestConfig
  ): Promise<ResultWithData<T>> {
    return this.service.get(url, { ...config })
  }

  public post<T>(url: string, data?: object): Promise<ResultWithData<T>> {
    return this.service.post(url, data)
  }

  public patch<T>(url: string, data?: object): Promise<ResultWithData<T>> {
    return this.service.patch(url, data)
  }

  public postFormData<T>(url: string, data?: unknown): Promise<ResultWithData<T>> {
    const headers = {
      'Content-Type': 'multipart/form-data'
    }
    return this.service.post(url, data, { headers })
  }

  public put<T>(url: string, data?: object): Promise<ResultWithData<T>> {
    return this.service.put(url, data)
  }

  public delete<T>(url: string, config?: AxiosRequestConfig): Promise<ResultWithData<T>> {
    return this.service.delete(url, { ...config })
  }
}

export default new RequestHttp(config)
